/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package sudokuTest;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import sudoku.ClassicCell;
import java.util.Map;
import java.util.ListIterator;
import java.util.LinkedList;
import junit.framework.Assert;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import sudoku.ClassicGrid;
import static org.junit.Assert.*;

/**
 *
 * @author taras
 */
public class ClassicGridTest {
    
    ClassicGrid grid;
    
    public ClassicGridTest() {
    }

    @BeforeClass
    public static void setUpClass() throws Exception {
    }

    @AfterClass
    public static void tearDownClass() throws Exception {
    }
    
    @Before
    public void setUp() {
        grid = new ClassicGrid();
    }
    
    @After
    public void tearDown() {
    }
    
    /**
     * Test of default constructor in ClassicGrid.
     */
    @Test
    public void testConstructorDef() {
        System.out.println("Default constructor.");
        
        Assert.assertEquals(grid.getLevel(), 3);
        Assert.assertEquals(grid.getUnsolvedCells(), 81);
        
        Assert.assertFalse(grid.getAccess().contains(false));
        for (int i=1; i<=9; i++) Assert.assertFalse(grid.getValues().contains(i));
    }
    
    /**
     * Test of default constructor in ClassicGrid.
     */
    @Test
    public void testConstructorCustom() {
        System.out.println("Custom constructor.");
        
        grid = new ClassicGrid(4);
        
        Assert.assertEquals(grid.getLevel(), 4);
        Assert.assertEquals(grid.getUnsolvedCells(), 256);
        
        Assert.assertFalse(grid.getAccess().contains(false));
        for (int i=1; i<=9; i++) Assert.assertFalse(grid.getValues().contains(i));
        
        grid = new ClassicGrid(5);
        
        Assert.assertEquals(grid.getLevel(), 5);
        Assert.assertEquals(grid.getUnsolvedCells(), 625);
        
        Assert.assertFalse(grid.getAccess().contains(false));
        for (int i=1; i<=9; i++) Assert.assertFalse(grid.getValues().contains(i));
    }
    
    /**
     * Test of default constructor in ClassicGrid.
     */
    @Test
    public void testClone() {
        System.out.println("Сlone method.");
        
        grid.userInsertValue(6, 1);
        grid.userInsertValue(10, 1);
        grid.userInsertValue(11, 3);
        grid.userInsertValue(22, 5);
        grid.userInsertValue(23, 6);
        grid.userInsertValue(25, 7);
        
        //grid.printGrid();
        
        ClassicGrid copy = grid.clone();
        
        //copy.printGrid();
        
        Assert.assertEquals(grid.getLevel(), copy.getLevel());
        Assert.assertEquals(grid.getUnsolvedCells(), copy.getUnsolvedCells());
        //Not sure about next two lines ...
        Assert.assertTrue(grid.getAccess().removeAll(copy.getAccess()));
        Assert.assertTrue(grid.getValues().removeAll(copy.getValues()));
        
        grid.userEraseValue(22);
        copy.userInsertValue(35, 9);
        
        Assert.assertFalse(grid.getUnsolvedCells() == copy.getUnsolvedCells());
        Assert.assertFalse(grid.getValues().contains(5));
        Assert.assertTrue(copy.getValues().contains(9));
    }  

    /**
     * @todo Do or remove test :)
     * Test of solveFastApproach method, of class ClassicGrid.
     */
    @Test
    public void testSolveFastApproach() {
        System.out.println("solveFastApproach"); 
        
        grid.solveFastApproach();
        
        if (grid.getUnsolvedCells() != 0){
            
            Map<Integer, ClassicCell> check = grid.getCopyGridMap();
            Iterator<Integer> it = check.keySet().iterator();
            while(it.hasNext()){
                Integer i = it.next();
                if (!check.get(i).getPossibleValues().isEmpty()){
                    fail();
                }
            } 
        }
    }
     

    /**
     * Test of userInsertValue method, of class ClassicGrid.
     */
    @Test
    public void testUserInsertValue() {
        System.out.println("userInsertValue");
        // good inputs
        grid.userInsertValue(6, 1);
        grid.userInsertValue(10, 1);
        grid.userInsertValue(11, 3);
        grid.userInsertValue(22, 5);
        grid.userInsertValue(23, 6);
        grid.userInsertValue(25, 7);
        
        Assert.assertEquals(grid.getUnsolvedCells(), 75);        
        ArrayList<Integer> list = grid.getValues();
        Assert.assertTrue(list.contains(1));
        Assert.assertTrue(list.contains(3));
        Assert.assertTrue(list.contains(5));
        Assert.assertTrue(list.contains(6));
        Assert.assertTrue(list.contains(7));
        
        //bad inputs
        grid.userInsertValue(0, 1);
        grid.userInsertValue(73, 1);
        grid.userInsertValue(18, 5);
        grid.userInsertValue(3, 5);
        grid.userInsertValue(77, 6);
        grid.userInsertValue(18, 7);
        grid.userInsertValue(17, 1);
        grid.userInsertValue(16, 3);
        grid.userInsertValue(78, 1);
        
        Assert.assertEquals(grid.getUnsolvedCells(), 75);
    }

    /**
     * Test of userEraseValue method, of class ClassicGrid.
     */
    @Test
    public void testUserEraseValue() {
        System.out.println("userEraseValue");
        // good inputs
        grid.userInsertValue(6, 1);
        grid.userInsertValue(10, 1);
        grid.userInsertValue(11, 3);
        grid.userInsertValue(22, 5);
        grid.userInsertValue(23, 6);
        grid.userInsertValue(25, 7);
        grid.userInsertValue(27, 4);
        grid.userInsertValue(39, 8);
        grid.userInsertValue(53, 1);
        grid.userInsertValue(55, 4);
        grid.userInsertValue(68, 5);
        grid.userInsertValue(61, 2);
        
        Assert.assertEquals(grid.getUnsolvedCells(), 69);
        
        //bad erasures
        grid.userEraseValue(5);
        grid.userEraseValue(8);
        grid.userEraseValue(28);
        grid.userEraseValue(60);
        grid.userEraseValue(54);
        
        Assert.assertEquals(grid.getUnsolvedCells(), 69);
        
        //good erasures
        grid.userEraseValue(6);
        grid.userEraseValue(22);
        grid.userEraseValue(27);
        grid.userEraseValue(55);
        grid.userEraseValue(39);
        
        Assert.assertEquals(grid.getUnsolvedCells(), 74); 
    }

    /**
     * Test of getLevel method, of class ClassicGrid.
     */
    @Test
    public void testGetLevel() {
        System.out.println("getLevel");
        
        for (int i = 2; i<6; i++){
            grid = new ClassicGrid(i);
            Assert.assertEquals(grid.getLevel(), i);
        }
        
        grid = new ClassicGrid(1);
        Assert.assertEquals(grid.getLevel(), 3);
        
        grid = new ClassicGrid(-51);
        Assert.assertEquals(grid.getLevel(), 3);
        
        grid = new ClassicGrid(61);
        Assert.assertEquals(grid.getLevel(), 3);
    }

    /**
     * Test of getUnsolvedCells method, of class ClassicGrid.
     */
    @Test
    public void testGetUnsolvedCells() {
        System.out.println("getUnsolvedCells");
        
        for (int i = 2; i<6; i++){
            grid = new ClassicGrid(i);
            Assert.assertEquals(grid.getUnsolvedCells(), (int) Math.pow(i, 4));
        }
        
        grid = new ClassicGrid(1);
        Assert.assertEquals(grid.getUnsolvedCells(), 81);
        
        grid = new ClassicGrid(-51);
        Assert.assertEquals(grid.getUnsolvedCells(), 81);
        
        grid = new ClassicGrid(61);
        Assert.assertEquals(grid.getUnsolvedCells(), 81);
    }

    /**
     * Test of getValues method, of class ClassicGrid.
     */
    @Test
    public void testGetValues() {
        System.out.println("getValues");
        
        ArrayList<Integer> list = grid.getValues();
        ListIterator<Integer> it = list.listIterator();
        
        int i=0;
        while(it.hasNext()){
            if (it.next()==0) i++;
        }
        Assert.assertEquals(i, 81);
        
        grid.insertRandomValues(20);
        
        list = grid.getValues();
        it = list.listIterator();
        
        i=0;
        while(it.hasNext()){
            if (it.next()==0) i++;
        }
        Assert.assertEquals(i, 61);
        
        int n = 0;
        for(int j=0; j<81; j++){
            for (int v=1; v<=9; v++){
                if (grid.userInsertValue(j, v)) n++;
            }
        }
        
        list = grid.getValues();
        it = list.listIterator();
        
        i=0;
        while(it.hasNext()){
            if (it.next()==0) i++;
        }
        Assert.assertEquals(i, 61-n);
    }

    /**
     * Test of getAccess method, of class ClassicGrid.
     */
    @Test
    public void testGetAccess() {
        System.out.println("getAccess");
        
        ArrayList<Boolean> list = grid.getAccess();
        ListIterator<Boolean> it = list.listIterator();
        
        int i=0;
        while(it.hasNext()){
            if (it.next()) i++;
        }
        Assert.assertEquals(i, 81);
        
        grid.insertRandomValues(20);
        
        list = grid.getAccess();
        it = list.listIterator();
        
        i=0;
        while(it.hasNext()){
            if (it.next()) i++;
        }
        Assert.assertEquals(i, 61);
        
        int n = 0;
        for(int j=0; j<81; j++){
            for (int v=1; v<=9; v++){
                if (grid.userInsertValue(j, v)) n++;
            }
        }
        
        list = grid.getAccess();
        it = list.listIterator();
        
        i=0;
        while(it.hasNext()){
            if (it.next()) i++;
        }
        Assert.assertEquals(i, 61);
    }
    
    /**
     * Test of compare method, of inner AnotherCellCompare class.
    
    @Test
    public void testCompare() {
        System.out.println("compare");
        
        ClassicCell c1 = new ClassicCell(0,0,0,9);
        ClassicCell c2 = new ClassicCell(0,0,0,9);
        ClassicCell c3 = new ClassicCell(0,0,0,9);
        
        ArrayList<ClassicCell> array = new ArrayList();
        
        array.add(c1);
        array.add(c2);
        array.add(c3);       
        
        Collections.sort(array, grid. new AnotherCellCompare());
        
        Assert.assertEquals(array.get(0).getValue(), 0);
        Assert.assertEquals(array.get(1).getValue(), 0);
        Assert.assertEquals(array.get(2).getValue(), 0);
        
        c2.setValue(2);
        Collections.sort(array, grid. new AnotherCellCompare());
        
        Assert.assertEquals(array.get(0).getValue(), 0);
        Assert.assertEquals(array.get(1).getValue(), 0);
        Assert.assertEquals(array.get(2).getValue(), 2);
        
        c1.setValue(1);
        Collections.sort(array, grid. new AnotherCellCompare());
        
        Assert.assertEquals(array.get(0).getValue(), 0);
        Assert.assertEquals(array.get(1).getValue(), 1);
        Assert.assertEquals(array.get(2).getValue(), 2);
        
        c2.eraseValue();
        Collections.sort(array, grid. new AnotherCellCompare());
        
        Assert.assertEquals(array.get(0).getValue(), 0);
        Assert.assertEquals(array.get(1).getValue(), 0);
        Assert.assertEquals(array.get(2).getValue(), 1);
        
        c3.setValue(3);
        Collections.sort(array, grid. new AnotherCellCompare());
        
        Assert.assertEquals(array.get(0).getValue(), 0);
        Assert.assertEquals(array.get(1).getValue(), 3);
        Assert.assertEquals(array.get(2).getValue(), 1);
    }
    */
   /**
     * Test of getCopyCell method.
    */
    @Test
    public void testGetCopyCell() {
        
        grid.userInsertValue(10, 5);
        ClassicCell copy = grid.getCopyCell(10);
        
        Assert.assertTrue(grid.getValues().get(10) == copy.getValue());
        
        copy.eraseValue();
        copy.setValue(4);
        Assert.assertFalse(grid.getValues().get(10) == copy.getValue());
    } 
    
    /**
     * Test of randomCellErase method.
    */
    @Test
    public void testRandomCellErase() {
        
        grid.insertRandomValues(40);
        
        int inNum = grid.getUnsolvedCells();
        
        grid.randomCellErase(((int) Math.pow(grid.getLevel(),4) - inNum)/2);
        
        Assert.assertTrue(grid.getUnsolvedCells() == (inNum + ((int) Math.pow(grid.getLevel(),4) - inNum)/2));
    } 
}
